package yf.mall.controller.api.dy;

import com.yf.annotation.IgnoreAuth;
import com.yf.annotation.LoginUserId;
import com.yf.response.R;
import com.yf.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.web.bind.annotation.*;
import yf.mall.common.Const;
import yf.mall.controller.api.app.ApiAppBaseController;
import yf.mall.dysdk.enums.AuthStatusEnum;
import yf.mall.dysdk.model.DyAuthCheckResponse;
import yf.mall.dysdk.model.DyAuthCodeResponse;
import yf.mall.dysdk.model.DyToken;
import yf.mall.dysdk.model.user.DyFullUserInfo;
import yf.mall.dysdk.model.user.DyUserInfo;
import yf.mall.dysdk.service.DyAuthService;
import yf.mall.dysdk.utils.DyUtil;
import yf.mall.entity.DyAccountAuthEntity;
import yf.mall.entity.UserEntity;
import yf.mall.service.app.DyAccountAuthService;
import yf.mall.service.app.KolOrderService;
import yf.mall.service.app.KolOrderStatService;
import yf.mall.vo.app.DyAuthRequestVo;
import yf.mall.vo.app.DyAuthUserInfoVo;
import yf.mall.vo.app.common.ListResult;
import yf.mall.vo.app.request.CommonRequest;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


@Slf4j
@RestController
@RequestMapping("/api/app/mini/account")
public class ApiAppDouyinAuthController extends ApiAppBaseController {

    @Resource
    private DyAuthService dyAuthService;

    @Resource
    private DyAccountAuthService dyAccountAuthService;

    @Resource
    private KolOrderService kolOrderService;

    @Resource
    private KolOrderStatService kolOrderStatService;


    @RequestMapping(value = "/oauth/connect",
            method = RequestMethod.POST)
    public R accountOauthConnect(@LoginUserId Long userId) {
        DyAuthCodeResponse response = dyAuthService.oauthConnect(userId);
        return R.ok(response);

    }


    @RequestMapping(value = "/oauth/query",
            produces = {"application/json"},
            consumes = {"application/json"},
            method = RequestMethod.POST)
    public R accountOauthQuery(@LoginUserId Long userId, @Valid @RequestBody DyAuthRequestVo request) {
        if (userId == null) {
            return R.notLogin();
        }
        DyAuthCheckResponse response = dyAuthService.oauthQuery(userId, request.getCode());
        if (response == null) {
            return R.error("请求抖音接口异常");
        }
        if (!Objects.equals(AuthStatusEnum.CONFIRMED.getValue(), response.getStatus())) {
            return R.ok(response);
        }
        HttpUrl httpUrl = HttpUrl.parse(response.getRedirectUrl());
        String code = httpUrl.queryParameter("code");
        String state = httpUrl.queryParameter("state");
        String stateUserId = DyUtil.decode(state);
        oAuthQueryAndSave(Long.parseLong(stateUserId), code);
        return R.ok(response);
    }

    @GetMapping("/oauth/get-query")
    @IgnoreAuth
    public R accountOauthQuery2(String code, String state, String scopes) {
        if (StringUtils.isBlank(code) || StringUtils.isBlank(state)) {
            return R.ok("未获取到授权code或state，暂不处理");
        }
        String userId = DyUtil.decode(state);
        if (StringUtils.isBlank(userId)) {
            return R.ok("未获取到授权user，暂不处理");
        }
        oAuthQueryAndSave(Long.parseLong(userId), code);
        return R.ok();
    }


    @RequestMapping("/douyin-account-list")
    public R accountList(@LoginUserId Long userId) {
        DyAccountAuthEntity query = new DyAccountAuthEntity();
        query.setUserId(userId);
        List<DyAccountAuthEntity> users = dyAccountAuthService.find(query);
        List<DyAuthUserInfoVo> dyAuthUserInfoVos = users.stream().map(user -> {

            DyAuthUserInfoVo userInfoVo = new DyAuthUserInfoVo();
            userInfoVo.setAvatar(user.getAvatar());
            userInfoVo.setFansCount(0L);
            userInfoVo.setId(userId);
            userInfoVo.setIsBlock(false);
            userInfoVo.setAuthTime(DateUtil.dateFormat("yyyy-MM-dd", user.getAuthTime()));
            userInfoVo.setIsExpired(DyUtil.isExpired(user.getAuthTime(), user.getExpiresIn()));
            userInfoVo.setNickName(user.getName());
            DyToken dyToken = new DyToken();
            dyToken.setAccessToken(user.getAccessToken());
            dyToken.setOpenId(user.getOpenId());
            String displayId = user.getUid();
            userInfoVo.setDisplayId(displayId);
            return userInfoVo;
        }).collect(Collectors.toList());
        return dataResult(new ListResult<>(dyAuthUserInfoVos, false));
    }

    @RequestMapping("/unbind")
    public R unBindDyAccount(@LoginUserId Long userId, @RequestBody CommonRequest request) {
        String uid = request.getUid();
        if (StringUtils.isBlank(uid)) {
            R.error("未获取到选择的抖音号");
        }
        List<DyAccountAuthEntity> dyAccountAuthEntities = dyAccountAuthService.getAllAuthByUser(userId);
        DyAccountAuthEntity matchAuth = dyAccountAuthEntities.stream().filter(authEntity -> Objects.equals(uid, authEntity.getUid())).findFirst().orElse(null);
        if (matchAuth == null) {
            return R.ok("该抖音号的授权记录已被删除");
        }
        // 删除对应绑定的抖音号
        dyAccountAuthService.delete(matchAuth.getId());

        // 如果删除的是主绑定账号，更新第一条为master
        if (matchAuth.getMaster() == 1) {
            DyAccountAuthEntity others = dyAccountAuthEntities.stream().filter(auth -> !Objects.equals(matchAuth.getId(), auth.getId())).findFirst().orElse(null);
            if (others != null) {
                others.setMaster(1);
                dyAccountAuthService.update(others);
            }
        }
        return R.ok();
    }

    @RequestMapping("/refresh-auth-info")
    public R refreshUserInfo(@LoginUserId Long userId) {
        List<DyAccountAuthEntity> allAuthByUser = dyAccountAuthService.getAllAuthByUser(userId);
        allAuthByUser.forEach(user -> {
            DyToken dyAccessToken = new DyToken();
            dyAccessToken.setAccessToken(user.getAccessToken());
            dyAccessToken.setRefreshToken(user.getRefreshToken());
            dyAccessToken.setExpiresIn(user.getExpiresIn());
            dyAccessToken.setOpenId(user.getOpenId());
            DyUserInfo userInfo = dyAuthService.getUserInfo(dyAccessToken);
            DyAccountAuthEntity updateEntity = new DyAccountAuthEntity();
            updateEntity.setId(user.getId());
            if (userInfo != null) {
                updateEntity.setName(userInfo.getNickname());
                updateEntity.setAvatar(userInfo.getAvatar());
            }
            String displayId = "dx_" + System.currentTimeMillis();
            DyFullUserInfo dyFullUserInfo = dyAuthService.getDyFullUserInfo(dyAccessToken.getOpenId());
            if (dyFullUserInfo == null || StringUtils.isBlank(dyFullUserInfo.getUniqueId())) {
                updateEntity.setUid(displayId);
            } else {
                updateEntity.setUid(dyFullUserInfo.getUniqueId());
                updateEntity.setSecUid(dyFullUserInfo.getSecUid());
            }
            dyAccountAuthService.update(updateEntity);
        });
        return R.ok();
    }

    @IgnoreAuth
    @RequestMapping("/notify-orders")
    public R notifyOrders(@RequestParam(required = false) Long userId, Integer day, @RequestParam(required = false) Integer limit) {
        if (limit == null) {
            limit = Const.DY_FIRST_BIND_MAX_QUERY_TIMES * Const.DY_ORDER_MAX_QUERY_SIZE;
        }
        Date begin = DateUtils.truncate(DateUtils.addDays(new Date(), -day), Calendar.DAY_OF_MONTH);
        if (userId != null) {
            kolOrderService.notifyOrderAsync(userId, begin, new Date(), limit);
        } else {
            kolOrderService.notifyOrderAsync(begin, new Date(), limit);
        }
        return R.ok();
    }





    private void oAuthQueryAndSave(Long userId, String code) {
        DyToken dyAccessToken = dyAuthService.getDyAccessToken(code);

        if (dyAccessToken == null) {
            return;
        }

        UserEntity userEntity = getLoginUser(userId);

        if (userEntity == null) {
            return;
        }

        DyAccountAuthEntity authEntity = new DyAccountAuthEntity();
        authEntity.setUserId(userId);
        authEntity.setAuthTime(new Date());
        authEntity.setAccessToken(dyAccessToken.getAccessToken());
        authEntity.setRefreshToken(dyAccessToken.getRefreshToken());
        authEntity.setExpiresIn(dyAccessToken.getExpiresIn());
        authEntity.setRefreshExpiresIn(dyAccessToken.getRefreshExpiresIn());
        authEntity.setNextRefreshTime(DateUtils.addSeconds(new Date(), dyAccessToken.getExpiresIn()));
        authEntity.setNextRenewRefreshTime(DateUtils.addSeconds(new Date(), dyAccessToken.getRefreshExpiresIn() - Const.DY_REFRESH_TOKEN_EARLIIER_SECOND));
        authEntity.setScope(dyAccessToken.getScope());
        authEntity.setOpenId(dyAccessToken.getOpenId());
        authEntity.setMaster(1);
        authEntity.setUserName(userEntity.getName());
        authEntity.setUserMobile(userEntity.getMobile());
        authEntity.setRemark("创建token信息");
        DyUserInfo userInfo = dyAuthService.getUserInfo(dyAccessToken);
        if (userInfo != null) {
            authEntity.setName(userInfo.getNickname());
            authEntity.setAvatar(userInfo.getAvatar());
        }
        try {
            String displayId = "dx_" + System.currentTimeMillis();
            DyFullUserInfo dyFullUserInfo = dyAuthService.getDyFullUserInfo(dyAccessToken.getOpenId());
            if (dyFullUserInfo == null || StringUtils.isBlank(dyFullUserInfo.getUniqueId())) {
                authEntity.setUid(displayId);
            } else {
                authEntity.setUid(dyFullUserInfo.getUniqueId());
                authEntity.setSecUid(dyFullUserInfo.getSecUid());
            }
        } catch (Exception e) {
        }

        boolean accountAuth = dyAccountAuthService.createAccountAuth(authEntity);

        if (accountAuth) {
            Date begin = DateUtils.truncate(DateUtils.addDays(new Date(), -89), Calendar.DAY_OF_MONTH);
            kolOrderService.notifyOrderAsync(userId, begin, new Date(), Const.DY_FIRST_BIND_MAX_QUERY_TIMES * Const.DY_ORDER_MAX_QUERY_SIZE);
        }
    }
}
